package com.m3839.sdk.common.widget.richtext;

import android.graphics.Color;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
import android.util.Log;
import android.view.View;

import org.xml.sax.XMLReader;

import java.util.Stack;

/**
 * 描述信息
 *
 * @author 徐智伟
 * @create 2020-03-27
 */
public class HtmlTagHandler implements Html.TagHandler {
  private static final String TAG = "HtmlTagHandler";
  /**
   * html标签
   */
  private static final String HTML_TAG_SPAN = "span";
  private static final String HTML_TAG_A = "ajump";
  private static final String CSS_NAME_COLOR = "color";
  private static final String CSS_NAME_FONT_SIZE = "font-size";

  /**
   * 存放各个标签的开始和结束标签下标
   */
  private Stack<Integer> indexStack;

  private OnTextClickListener onTextClickListener;

  public HtmlTagHandler(OnTextClickListener listener) {
    indexStack = new Stack<>();
    this.onTextClickListener = listener;
  }

  @Override
  public void handleTag(boolean opening, String tag, Editable output,
      XMLReader xmlReader) {

    if (opening) {
      //process start tag,like <span>
      handleStartTag(tag, output, xmlReader);

      indexStack.push(output.length());

    } else {
      //process end tag, like "</span>"

      int startIndex;
      if (indexStack.isEmpty()) {
        startIndex = 0;
      }  else {
        startIndex = indexStack.pop();
      }

      //结束标签逻辑处理
      handleEndTag(startIndex, output.length(), tag,
          output, xmlReader);
    }

  }

  private void handleStartTag(String tag, Editable output,
      XMLReader xmlReader) {

    switch (tag.toLowerCase()) {
      case HTML_TAG_SPAN:
        spanStartTag(tag,output,xmlReader);
        break;
      case HTML_TAG_A:
        aStartTag(tag, output, xmlReader);
        break;
      default:
        break;
    }
  }

  private void handleEndTag(int startIndex, int endIndex,String tag, Editable output,
      XMLReader xmlReader) {
    switch (tag.toLowerCase()) {
      case HTML_TAG_SPAN:
        spanEndTag(startIndex, endIndex, tag, output, xmlReader);
        break;
      case HTML_TAG_A:
        aEndTag(startIndex, endIndex, tag, output, xmlReader);
        break;
      default:
        break;
    }
  }

  /**
   * 开始span标签处理
   * @param tag
   * @param output
   * @param xmlReader
   */
  private void spanStartTag(String tag, Editable output,
      XMLReader xmlReader) {

    String styleCss = HtmlTagHelper.getAttribute(xmlReader, "style");

    parseCssStyle(styleCss, output);
  }

  /**
   * span结束标签处理
   * @param startIndex
   * @param endIndex
   * @param tag
   * @param output
   * @param xmlReader
   */
  private void spanEndTag(int startIndex, int endIndex,String tag, Editable output,
      XMLReader xmlReader) {
    CssStyle cssStyle = HtmlTagHelper.getLast(output, CssStyle.class);

    if (cssStyle == null) {
      return;
    }

    if (cssStyle.color != 0) {
      int where = output.getSpanStart(cssStyle);
      output.removeSpan(cssStyle);

      //移除原有标记，因为原有标记不是默认的24种ParcelableSpan子类，因此无法渲染文本
      output.setSpan(new ForegroundColorSpan(cssStyle.color),
          where, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

  }

  /**
   * 开始span标签处理
   * @param tag
   * @param output
   * @param xmlReader
   */
  private void aStartTag(String tag, Editable output,
      XMLReader xmlReader) {
    String href = HtmlTagHelper.getAttribute(xmlReader, "href");

    int length = output.length();

    output.setSpan(new LinkHolder(href),length, length,
        Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
  }

  /**
   * span结束标签处理
   * @param startIndex
   * @param endIndex
   * @param tag
   * @param output
   * @param xmlReader
   */
  private void aEndTag(int startIndex, int endIndex,String tag, Editable output,
      XMLReader xmlReader) {

    final LinkHolder linkHolder = HtmlTagHelper.getLast(output, LinkHolder.class);

    if (linkHolder != null) {
      int start = output.getSpanStart(linkHolder);
      // int end = output.getSpanEnd(linkHolder);
      output.removeSpan(linkHolder);

      output.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
          if (onTextClickListener != null) {
            onTextClickListener.onTextClick(linkHolder.url);
          }

          Log.i(TAG, "click custom url =" + linkHolder.url);
        }
      }, start, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }



    /*URLSpan[] urlSpans = output.getSpans(0, output.length(), URLSpan.class);

    int size = urlSpans == null ? 0 : urlSpans.length;
    for (int i = 0; i < size; i ++) {
      resetLinkSpan(output, urlSpans[i]);
    }*/

  }

  private void resetLinkSpan(Spannable spanned, URLSpan urlSpan) {
    int start = spanned.getSpanStart(urlSpan);
    int end = spanned.getSpanEnd(urlSpan);
    spanned.removeSpan(urlSpan);

    final LinkHolder linkHolder = new LinkHolder(urlSpan.getURL());

    spanned.setSpan(new ClickableSpan() {
      @Override
      public void onClick(View widget) {
        if (onTextClickListener != null) {
          onTextClickListener.onTextClick(linkHolder.url);
        }
      }
    }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  }





  /**
   * css样式解析
   * @param style
   * @param output
   */
  private void parseCssStyle(String style,Editable output){

    if(TextUtils.isEmpty(style)) {
      return;
    }

    int length = output.length();
    String[] cssArray = style.split(";");

    //颜色值
    int color = 0;

    for (String css : cssArray) {
      if (TextUtils.isEmpty(css)) {
        break;
      }

      String[] splitCss = css.trim().split(":");
      String cssName = splitCss[0];

      //判断是否是color
      if (CSS_NAME_COLOR.equals(cssName.trim())) {

        String colorString = splitCss[1].trim().replaceAll(" ","")
            .toLowerCase();
        color = parseColor(colorString);


        output.setSpan(new CssStyle(0, color),length, length,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      }

    }

  }

  /**
   * 解析颜色值
   * @param colorString
   * @return
   */
  private int parseColor(String colorString) {
    int color = 0;

    if (colorString.startsWith("rgb") || colorString.startsWith("rgba")) {

      int start = colorString.indexOf("(");
      int end = colorString.indexOf(")");
      colorString = colorString.substring(start, end);
      colorString = colorString.replaceAll(" ","").replaceAll("\\(","");
      String[] colorArray = colorString.split(",");

      if (colorArray.length == 3) {
        color = Color.argb(255,Integer.parseInt(colorArray[0]),
            Integer.parseInt(colorArray[1]),
            Integer.parseInt(colorArray[2]));

      } else {
        color = Color.argb(Integer.parseInt(colorArray[3]),
            Integer.parseInt(colorArray[0]),
            Integer.parseInt(colorArray[1]),
            Integer.parseInt(colorArray[2]));
      }

    } else if (colorString.length() == 7) {
      //后台传的color可能出现非标准的值，这里
      color = Color.parseColor(colorString);
    }

    return color;
  }

  private static class LinkHolder {

    /**
     * 默认颜色值
     */
    private static final int LINK_COLOR = Color.parseColor("#00ff00");
    public String url;

    public int color;
    /**
     * 下划线标识
     */
    boolean underLine;

    public LinkHolder(String url) {

      this(url,LINK_COLOR);
    }

    public LinkHolder(String url, int color) {
      this(url, color, false);
    }

    public LinkHolder(String url, int color, boolean underLine) {
      this.url = url;
      this.color = color;
      this.underLine = underLine;
    }
  }

  /*
   *自定义
   */
  private static class CssStyle {
    int textSize;
    int color;

    public CssStyle(int textSize, int color) {
      this.textSize = textSize;
      this.color = color;
    }
  }

  private static class ATagSpan {
    String href;

    public ATagSpan(String href) {
      this.href = href;
    }
  }

  public interface OnTextClickListener {
    void onTextClick(String textUrl);
  }
}

